package framework.service {
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import org.osflash.signals.natives.NativeSignal;
	import org.osflash.signals.Signal;

	/**
	 * @author Charlie MacIsaac
	 */
	
	public class LoaderSignalsWrapper {
		// PROPERTIES =============================================================================
		public var complete : Signal;
		
		private var _loadCompleteSignal : NativeSignal;
		private var _progressSignal : NativeSignal;
		private var _loadFailedSignal : NativeSignal;
		
		private var _dataLoader : URLLoader;
		private var _imageLoader : Loader;
		
		private var _urlRequest : URLRequest;
		
		// GETTERS + SETTERS ======================================================================
		private function get isData() : Boolean {
			var type : String = _urlRequest.url.substr(_urlRequest.url.length - 4, 4);
			
			switch (type) {
				case ".swf" : 
				case ".png" : 
				case ".jpg" : 
				case ".gif" : 
					return false;
				default :
					return true;
			}
		}
		
		// CONSTRUCTOR ============================================================================
		public function LoaderSignalsWrapper() {
			complete = new Signal();
		}
		
		// PUBLIC =================================================================================
		public function load(url : String) : void {
			_urlRequest = new URLRequest(url);
			
			if (isData) {
				_dataLoader = new URLLoader();
				configureSignals(_dataLoader);
				_dataLoader.load(_urlRequest);
			} else {
				_imageLoader = new Loader();
				configureSignals(_imageLoader.contentLoaderInfo);
				_imageLoader.load(_urlRequest, new LoaderContext(false, ApplicationDomain.currentDomain));
			}
		}
		
		// PRIVATE ================================================================================
		private function configureSignals(target : IEventDispatcher) : void {
			_loadCompleteSignal = new NativeSignal(target, Event.COMPLETE, Event);
			_progressSignal = new NativeSignal(target, ProgressEvent.PROGRESS, ProgressEvent);
			_loadFailedSignal = new NativeSignal(target, IOErrorEvent.IO_ERROR, IOErrorEvent);
			
			_loadCompleteSignal.addOnce(loadCompleteHandler);
			_progressSignal.add(progressHandler);
			_loadFailedSignal.addOnce(loadFailedHandler);
		}
		
		// LISTENERS ==============================================================================
		private function loadCompleteHandler(e : Event) : void {
			var loadedData : Object = isData ? _dataLoader.data : _imageLoader.content;
			_progressSignal.removeAll();
			complete.dispatch(loadedData);
		}
		
		private function progressHandler(e : ProgressEvent) : void {
			var percentageLoaded : Number = (e.bytesLoaded / e.bytesTotal);
			trace("[LoaderSignalsWrapper.progressHandler] |" + _urlRequest.url + "| " + uint(percentageLoaded * 100));
		}
		
		private function loadFailedHandler(e : IOErrorEvent) : void {
			_progressSignal.removeAll();
			throw new Error("[LoaderSignalsWrapper.loadFailedHandler] |ERROR| There has been an error while loading the url : " + _urlRequest.url);
		}
	}
}